/*
* Sun Public License Notice
*
* The contents of this file are subject to the Sun Public License
* Version 1.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://www.sun.com/
*
* The Original Code is NetBeans. The Initial Developer of the Original
* Code is Sun Microsystems, Inc. Portions Copyright 1997-2001 Sun
* Microsystems, Inc. All Rights Reserved.
*/
package org.netbeans.modules.db.explorer.infos;
import java.io.InputStream;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.beans.*;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.*;
import java.sql.*;
import org.netbeans.lib.ddl.*;
import org.netbeans.lib.ddl.adaptors.*;
import org.netbeans.lib.ddl.impl.*;
import org.netbeans.lib.ddl.util.PListReader;
import org.netbeans.modules.db.DatabaseException;
import org.netbeans.modules.db.explorer.*;
import org.netbeans.modules.db.explorer.nodes.*;
import org.netbeans.modules.db.explorer.actions.DatabaseAction;
import org.openide.*;
import org.openide.nodes.Node;
import org.openide.util.actions.SystemAction;
import org.openide.util.NbBundle;
public class DatabaseNodeInfo extends Hashtable implements Node.Cookie
{
public static final String SPECIFICATION_FACTORY = "specfactory";
public static final String SPECIFICATION = "spec";
public static final String DRIVER_SPECIFICATION = "drvspec";
public static final String DBPRODUCT = "dbproduct";
public static final String DBVERSION = "dbversion";
public static final String SUPPORTED_DBS = "suppdbs";
public static final String DRIVER = "driver";
public static final String DBDRIVER = "dbdriver";
public static final String DATABASE = "db";
public static final String URL = "url";
public static final String PREFIX = "prefix";
public static final String CONNECTION = "connection";
public static final String CODE = "code";
public static final String NODE = "node";
public static final String CLASS = "class";
public static final String INFOCLASS = "infoclass";
public static final String NAME = "name";
public static final String USER = "user";
public static final String PASSWORD = "password";
public static final String CHILDREN = "children";
public static final String ACTIONS = "actions";
public static final String ICONBASE = "iconbase";
public static final String PROPERTIES = "properties";
public static final String RESULTSET = "resultset";
public static final String REMEMBER_PWD = "rememberpwd";
public static final String WRITABLE = "writable";
public static final String DELETABLE = "deletable";
public static final String DESCRIPTION = "description";
public static final String READONLYDB = "readonlydatabase";
public static final String GROUPSUP = "groupbysupport";
public static final String OJOINSUP = "outerjoinsupport";
public static final String UNIONSUP = "unionsupport";
public static final String SYSTEM_ACTION = "system";
public static final String CHILDREN_ORDERING = "children_ordering";
public static final String READONLY = "readOnly";
public static final String PERM = "perm";
public static final String ADAPTOR = "adaptor";
public static final String ADAPTOR_CLASSNAME = "adaptorClass";
private static Map gtab = null;
private static final String gtabfile = "org/netbeans/modules/db/resources/explorer.plist";
public static Map getGlobalNodeInfo()
{
if (gtab == null) try {
ClassLoader cl = DatabaseNodeInfo.class.getClassLoader();
InputStream stream = cl.getResourceAsStream(gtabfile);
if (stream == null) throw new Exception("unable to open stream "+gtabfile);
PListReader reader = new PListReader(stream);
gtab = reader.getData();
stream.close();
} catch (Exception e) {
e.printStackTrace();
gtab = null;
}
return gtab;
}
public static Object getGlobalNodeInfo(String key)
{
return getGlobalNodeInfo().get(key);
}
public static DatabaseNodeInfo createNodeInfo(DatabaseNodeInfo parent, String nodecode)
throws DatabaseException
{
DatabaseNodeInfo e_ni = null;
try {
String nodec = (String)((Map)DatabaseNodeInfo.getGlobalNodeInfo().get(nodecode)).get(INFOCLASS);
if (nodec != null) e_ni = (DatabaseNodeInfo)Class.forName(nodec).newInstance();
else throw new Exception("unable to find class information for "+nodecode);
} catch (Exception e) {
e.printStackTrace();
throw new DatabaseException(e.getMessage());
}
if (e_ni != null) e_ni.setParentInfo(parent, nodecode);
else throw new DatabaseException("unable to create node information "+nodecode);
return e_ni;
}
public static DatabaseNodeInfo createNodeInfo(DatabaseNodeInfo parent, String nodecode, ResultSet rset)
throws DatabaseException
{
int colidx = 1;
String key = null;
DatabaseNodeInfo nfo = createNodeInfo(parent, nodecode);
Vector rsnames = (Vector)nfo.get(DatabaseNodeInfo.RESULTSET);
Iterator rsnames_i = rsnames.iterator();
Hashtable data = new Hashtable();
while (rsnames_i.hasNext())
try {
key = (String)rsnames_i.next();
if (!key.equals("unused")) {
Object value = rset.getObject(colidx);
if (value != null) data.put(key, value);
}
colidx++;
} catch (SQLException ex) {
// ex.printStackTrace();
// System.out.println("createNodeInfo: " + ex);
}
nfo.putAll(data);
nfo.put(nodecode, nfo.getName());
if (parent != null && parent.isReadOnly()) nfo.setReadOnly(true);
return nfo;
}
/* Parent of info in node hierarchy */
private DatabaseNodeInfo parent = null;
/* Owning node */
WeakReference nodewr = null;
private PropertyChangeSupport pcs = null;
private PropertyChangeSupport driverpcs = null;
/**
* @associates String
*/
private Set driverpcsKeys = null;
static final long serialVersionUID =1176243907461868244L;
public DatabaseNodeInfo()
{
super();
}
public DatabaseNodeInfo(DatabaseNodeInfo parent, String sname)
throws DatabaseException
{
DatabaseNodeInfo nfo = new DatabaseNodeInfo();
nfo.setParentInfo(parent, sname);
}
public void setParentInfo(DatabaseNodeInfo parent, String sname)
throws DatabaseException
{
if (parent != null) {
putAll(parent);
this.parent = parent;
}
Map ltab = (Map)getGlobalNodeInfo(sname);
if (ltab != null) putAll(ltab);
else throw new DatabaseException("unable to read information for "+sname);
put(CODE, sname);
if (parent != null && parent.isReadOnly()) setReadOnly(true);
}
public DatabaseNodeInfo getParent()
{
return parent;
}
/** Returns parent of nodeinfo defined by <code>parent</code> variable.
* If no info was found, it returns null.
*/
public DatabaseNodeInfo getParent(String code)
{
DatabaseNodeInfo iinfo = this;
if (code != null) {
while (iinfo != null) {
String iicode = iinfo.getCode();
if (iicode.equals(code)) return iinfo;
else iinfo = iinfo.getParent();
}
}
return iinfo;
}
public boolean canAdd(Map propmap, String propname)
{
return true;
}
public boolean canWrite(Map propmap, String propname, boolean defa)
{
if (isReadOnly()) return false;
String wflag = (String)propmap.get(DatabaseNodeInfo.WRITABLE);
if (wflag != null) return wflag.toUpperCase().equals("YES");
return defa;
}
public DatabaseNode getNode()
{
if (nodewr != null) return (DatabaseNode)nodewr.get();
return null;
}
public void setNode(DatabaseNode node)
{
nodewr = new WeakReference(node);
}
private PropertyChangeSupport getConnectionPCS()
{
if (pcs == null)
pcs = new PropertyChangeSupport(this);
return pcs;
}
/** Returns PropertyChangeSupport used for driver change monitoring */
private PropertyChangeSupport getDriverPCS()
{
if (driverpcs == null)
driverpcs = new PropertyChangeSupport(this);
return driverpcs;
}
/** Returns PropertyChangeSupport used for driver change monitoring */
private Set getDriverPCSKeys()
{
if (driverpcsKeys == null) {
driverpcsKeys = new HashSet();
driverpcsKeys.add(NAME);
driverpcsKeys.add(URL);
driverpcsKeys.add(PREFIX);
driverpcsKeys.add(ADAPTOR_CLASSNAME);
}
return driverpcsKeys;
}
public Object put(Object key, Object obj)
{
Object old = get(key);
if (key == null)
throw new NullPointerException();
if (obj != null)
super.put(key, obj);
else
remove(key);
if (getDriverPCSKeys().contains(key))
getDriverPCS().firePropertyChange((String)key, old, obj);
else
if (key.equals(DATABASE))
getConnectionPCS().firePropertyChange(DATABASE, old, obj);
return old;
}
public void delete() throws IOException
{
}
public void refreshChildren() throws DatabaseException
{
}
/** Called by property editor */
public Object getProperty(String key)
{
return get(key);
}
/** Called by property editor */
public void setProperty(String key, Object obj)
{
put(key, obj);
}
/** Add property change listener */
public void addConnectionListener(PropertyChangeListener l)
{
getConnectionPCS().addPropertyChangeListener(l);
}
/** Remove property change listener */
public void removeConnectionListener(PropertyChangeListener l)
{
pcs.removePropertyChangeListener(l);
}
public void addDriverListener(PropertyChangeListener l)
{
getDriverPCS().addPropertyChangeListener(l);
}
public void removeDriverListener(PropertyChangeListener l)
{
getDriverPCS().removePropertyChangeListener(l);
}
public DatabaseSpecificationFactory getSpecificationFactory()
{
return (DatabaseSpecificationFactory)get(SPECIFICATION_FACTORY);
}
public void setSpecificationFactory(DatabaseSpecificationFactory fac)
{
put(SPECIFICATION_FACTORY, fac);
put(SUPPORTED_DBS, fac.supportedDatabases());
}
protected String getDatabaseAdaptorClassName()
{
String adac = null;
String drv = getDriver();
DatabaseOption option = RootNode.getOption();
Vector drvs = option.getAvailableDrivers();
Enumeration enu = drvs.elements();
while (enu.hasMoreElements()) {
DatabaseDriver driver = (DatabaseDriver)enu.nextElement();
if (driver.getURL().equals(drv)) adac = driver.getDatabaseAdaptor();
}
if (adac == null) adac = "org.netbeans.lib.ddl.adaptors.DefaultAdaptor";
return adac;
}
public DatabaseSpecification getSpecification()
{
DatabaseSpecification spec = (DatabaseSpecification)get(SPECIFICATION);
if (spec == null) return spec;
String adaname = getDatabaseAdaptorClassName();
if (!spec.getMetaDataAdaptorClassName().equals(adaname)) {
spec.setMetaDataAdaptorClassName(adaname);
}
return spec;
}
public void setSpecification(DatabaseSpecification spec)
{
put(SPECIFICATION, spec);
}
public String getDriver()
{
return (String)get(DRIVER);
}
public void setDriver(String drv)
{
put(DRIVER, drv);
}
public Connection getConnection()
{
return (Connection)get(CONNECTION);
}
public void setConnection(Connection con) throws DatabaseException
{
Connection oldval = getConnection();
if (con != null) {
if (oldval != null && oldval.equals(con)) return;
put(CONNECTION, con);
} else remove(CONNECTION);
// Check if node is readonly or not.
if (con != null && isReadOnly()) {
Enumeration enu = getChildren().elements();
while(enu.hasMoreElements()) {
DatabaseNodeInfo ninfo = (DatabaseNodeInfo)enu.nextElement();
ninfo.setReadOnly(true);
}
}
getConnectionPCS().firePropertyChange(CONNECTION, oldval, con);
}
public DBConnection getDatabaseConnection()
{
DatabaseConnection con = new DatabaseConnection(getDriver(), getDatabase(), getUser(), getPassword()); con.setRememberPassword(((Boolean)get(REMEMBER_PWD)).booleanValue());
return con;
}
public DatabaseDriver getDatabaseDriver()
{
return (DatabaseDriver)get(DBDRIVER);
}
public void setDatabaseConnection(DBConnection cinfo)
{
String pwd = cinfo.getPassword();
put(DRIVER, cinfo.getDriver());
put(DATABASE, cinfo.getDatabase());
put(USER, cinfo.getUser());
if (pwd != null) put(PASSWORD, pwd);
put(REMEMBER_PWD, (cinfo.rememberPassword() ? new Boolean(true) : new Boolean(false)));
}
public String getCode()
{
return (String)get(CODE);
}
public void setCode(String nam)
{
put(CODE, nam);
}
public String getName()
{
return (String)get(NAME);
}
public void setName(String nam)
{
put(NAME, nam);
}
public String getUser()
{
return (String)get(USER);
}
public void setUser(String usr)
{
put(USER, usr);
}
public String getDatabase()
{
return (String)get(DATABASE);
}
public void setDatabase(String db)
{
put(DATABASE, db);
}
public String getPassword()
{
return (String)get(PASSWORD);
}
public void setPassword(String pwd)
{
put(PASSWORD, pwd);
}
public String getTable()
{
return (String)get("table");
}
public void setTable(String nam)
{
put("table", nam);
}
public String getIconBase()
{
return (String)get("iconbase");
}
public void setIconBase(String base)
{
put("iconbase", base);
}
public String getDisplayname()
{
return (String)get("displayname");
}
public void setDisplayname(String name)
{
put("displayname", name);
}
public String getURL()
{
return (String)get(URL);
}
public void setURL(String url)
{
put(URL, url);
}
/** Returns connection properties (login name and password)
* Returns null if name or password isn't specified yet.
*/
public Properties getConnectionProperties()
{
Properties props = new Properties();
try {
props.put("user", getUser());
props.put("password", getPassword());
} catch (Exception e) { props = null; }
return props;
}
protected void initChildren(Vector children)
throws DatabaseException
{
}
public Vector getChildren()
throws DatabaseException
{
Vector children = (Vector)get(CHILDREN);
if (children.size() > 0 && children.elementAt(0) instanceof DatabaseNodeInfo) return children;
Vector chalt = new Vector();
initChildren(chalt);
chalt.addAll(children);
try {
for (int i=0; i<chalt.size();i++) {
Object e_child = chalt.elementAt(i);
if (e_child instanceof String) {
DatabaseNodeInfo e_ni = createNodeInfo(this, (String)e_child);
chalt.setElementAt(e_ni,i);
}
}
children = chalt;
put(CHILDREN, children);
} catch (Exception e) {
throw new DatabaseException("unable to create children, "+e.getMessage());
}
return children;
}
public void setChildren(Vector chvec)
{
put(CHILDREN, chvec);
}
public Vector getActions()
{
Vector actions = (Vector)get(ACTIONS);
if (actions == null) {
actions = new Vector();
put(ACTIONS, actions);
}
if (actions.size() == 0) return actions;
ResourceBundle bundle = NbBundle.getBundle("org.netbeans.modules.db.resources.Bundle");
Object xaction = actions.elementAt(0);
if (xaction != null && xaction instanceof DatabaseAction) return actions;
boolean ro = isReadOnly();
for (int i=0; i<actions.size();i++) {
Object e_act = actions.elementAt(i);
SystemAction action = null;
if (e_act instanceof Map) {
Map e_action = (Map)e_act;
try {
// Try permissions
String perm = (String)e_action.get(PERM);
if (ro && perm != null && perm instanceof String && perm.indexOf("write") != -1) {
actions.setElementAt(null, i);
continue;
}
boolean systemact = false;
String sysactstr = (String)e_action.get(SYSTEM_ACTION);
if (sysactstr != null) systemact = sysactstr.toUpperCase().equals("YES");
String actnode = (String)e_action.get(NODE);
String actcn = (String)e_action.get(CLASS);
if (!systemact) {
String locname, xname = (String)e_action.get(NAME);
try {
locname = bundle.getString(xname);
} catch (MissingResourceException e) {
locname = xname;
System.out.println("unable to locate localized menu item "+xname);
}
action = (SystemAction)Class.forName(actcn).newInstance();
((DatabaseAction)action).setName(locname);
((DatabaseAction)action).setNode(actnode);
} else action = SystemAction.get(Class.forName(actcn));
} catch (Exception e) {
e.printStackTrace();
}
}
actions.setElementAt(action, i);
}
return actions;
}
public String toString()
{
String result = "";
Enumeration keys = keys();
while (keys.hasMoreElements()) {
Object key = keys.nextElement();
result = result + key+": "+get(key)+ "\n";
}
return result;
}
public boolean isDebugMode()
{
return RootNode.getOption().getDebugMode();
}
public void setDebugMode(boolean mode)
{
RootNode.getOption().setDebugMode(mode);
}
public boolean isReadOnly()
{
Boolean roobj = (Boolean)get(READONLY);
if (roobj != null) return roobj.booleanValue();
return false;
}
public void setReadOnly(boolean flag)
{
put(READONLY, new Boolean(flag));
}
/** Getter for property driverSpecification.
*@return Value of property driverSpecification.
*/
public DriverSpecification getDriverSpecification() {
return (DriverSpecification) get(DRIVER_SPECIFICATION);
}
/** Setter for property driverSpecification.
*@param driverSpecification New value of property driverSpecification.
*/
public void setDriverSpecification(DriverSpecification driverSpecification) {
put(DRIVER_SPECIFICATION, driverSpecification);
}
}
/*
* <<Log>>
* 23 Gandalf 1.22 1/25/00 Radko Najman new driver adaptor
* version
* 22 Gandalf 1.21 12/22/99 Radko Najman debug message
* 21 Gandalf 1.20 12/15/99 Radko Najman driver adaptor
* 20 Gandalf 1.19 11/27/99 Patrik Knakal
* 19 Gandalf 1.18 11/15/99 Radko Najman
* 18 Gandalf 1.17 11/15/99 Radko Najman
* 17 Gandalf 1.16 11/8/99 Radko Najman ConnectionNode name
* refresh
* 16 Gandalf 1.15 10/23/99 Ian Formanek NO SEMANTIC CHANGE - Sun
* Microsystems Copyright in File Comment
* 15 Gandalf 1.14 9/13/99 Slavek Psenicka
* 14 Gandalf 1.13 9/13/99 Slavek Psenicka
* 13 Gandalf 1.12 9/13/99 Slavek Psenicka
* 12 Gandalf 1.11 9/8/99 Slavek Psenicka adaptor changes
* 11 Gandalf 1.10 9/2/99 Slavek Psenicka ReadOnly and permissions
* features
* 10 Gandalf 1.9 8/19/99 Slavek Psenicka English
* 9 Gandalf 1.8 8/18/99 Slavek Psenicka debug log removed
* 8 Gandalf 1.7 8/18/99 Slavek Psenicka debug logs removed
* 7 Gandalf 1.6 7/21/99 Slavek Psenicka don't remember password
* 6 Gandalf 1.5 6/10/99 Slavek Psenicka new folder icon
* 5 Gandalf 1.4 6/9/99 Ian Formanek ---- Package Change To
* org.openide ----
* 4 Gandalf 1.3 5/21/99 Slavek Psenicka new version
* 3 Gandalf 1.2 5/14/99 Slavek Psenicka new version
* 2 Gandalf 1.1 4/23/99 Slavek Psenicka Debug mode
* 1 Gandalf 1.0 4/23/99 Slavek Psenicka
* $
*/